import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class ChromoFloat extends Chromo{
	
	
	private float randnum;
	
	public ChromoFloat() {

		//  Create random float numbers
		float geneBit;
		this.chromofloat = new float [Parameters.geneSize];
		for (int i=0; i<Parameters.numGenes; i++){
			for (int j=0; j<Parameters.geneSize; j++){
				if(Search.r.nextBoolean() == true){
					randnum = Search.r.nextInt(10000);
				}else{
					randnum = Search.r.nextInt(10000) * -1;
				}
				geneBit = randnum;
				this.chromofloat[j] = (float)geneBit;
			}
		}
		this.rawFitness = -1;   //  Fitness not yet evaluated
		this.sclFitness = -1;   //  Fitness not yet scaled
		this.proFitness = -1;   //  Fitness not yet proportionalized
	}


	//  Mutate a Chromosome Based on Mutation Type *****************************
	@Override
	public void doMutation(){
		Boolean choice;
		
		float[] mutChromoFloat = new float[Parameters.geneSize];
		float x;
		double rand;
		switch (Parameters.mutationType){

		case 1:     //  Replace with new random number

			for (int j=0; j<(Parameters.geneSize * Parameters.numGenes); j++){
				x = this.chromofloat[j];
				rand = Search.r.nextDouble();
				choice = Search.r.nextBoolean();
				if (rand < Parameters.mutationRate){
					
					if(choice){
						x = Search.r.nextInt(10000);
					}else{
						x = Search.r.nextInt(10000) * -1;
					}
				}
				mutChromoFloat[j] = x;
			}
			
			this.chromofloat = mutChromoFloat;
			break;

		default:
			System.out.println("ERROR - No mutation method selected");
		}
	}

/*******************************************************************************
*                             STATIC METHODS                                   *
*******************************************************************************/

	//  Select a parent for crossover ******************************************
	@Override
	public int selectParent(Chromo[] member){

		double rWheel = 0;
		int j = 0;

		switch (Parameters.selectType){

		case 1:     // Proportional Selection
			randnum = Search.r.nextFloat();
			for (j=0; j<Parameters.popSize; j++){
				rWheel = rWheel + member[j].proFitness;
				if (randnum < rWheel) return(j);
			}
			break;

		case 3:     // Random Selection
			randnum = Search.r.nextFloat();
			j = (int) (randnum * Parameters.popSize);
			return(j);

		case 2:     //  Tournament Selection

		default:
			System.out.println("ERROR - No selection method selected");
		}
	return(-1);
	}

	//  Produce a new child from two parents  **********************************
	@Override
	public void mateParents(int pnum1, int pnum2, Chromo parent1, Chromo parent2, Chromo child1, Chromo child2){

		int xoverPoint1;
		int xoverPoint2;

		switch (Parameters.xoverType){

		case 1:     //  Single Point Crossover

			//  Select crossover point
			xoverPoint1 = Search.r.nextInt(4);
			
			if(xoverPoint1 == 0){
				xoverPoint1++;
			}
			
			//  Create child 1 chromosome from parental material
			for (int i=0; i<Parameters.numGenes; i++){
				for (int j=0; j<Parameters.geneSize; j++){
					if(j>=xoverPoint1){
						child2.chromofloat[j] = parent1.chromofloat[j];
						child1.chromofloat[j] = parent2.chromofloat[j];
					}else{
						child2.chromofloat[j] = parent2.chromofloat[j];
						child1.chromofloat[j] = parent1.chromofloat[j];
					}
				}
			}
			break;

		case 2:     //  Two Point Crossover

		case 3:     //  Uniform Crossover

		default:
			System.out.println("ERROR - Bad crossover method selected");
		}

		//  Set fitness values back to zero
		child1.rawFitness = -1;   //  Fitness not yet evaluated
		child1.sclFitness = -1;   //  Fitness not yet scaled
		child1.proFitness = -1;   //  Fitness not yet proportionalized
		child2.rawFitness = -1;   //  Fitness not yet evaluated
		child2.sclFitness = -1;   //  Fitness not yet scaled
		child2.proFitness = -1;   //  Fitness not yet proportionalized
	}

	//  Produce a new child from a single parent  ******************************
	@Override
	public void mateParents(int pnum, Chromo parent, Chromo child){

		//  Create child chromosome from parental material
		child.chromofloat = parent.chromofloat;

		//  Set fitness values back to zero
		child.rawFitness = -1;   //  Fitness not yet evaluated
		child.sclFitness = -1;   //  Fitness not yet scaled
		child.proFitness = -1;   //  Fitness not yet proportionalized
	}



	//  Copy one chromosome to another  ***************************************
	@Override
	public void copyB2A (Chromo targetA, Chromo sourceB){

		targetA.chromofloat = sourceB.chromofloat;

		targetA.rawFitness = sourceB.rawFitness;
		targetA.sclFitness = sourceB.sclFitness;
		targetA.proFitness = sourceB.proFitness;
		return;
	}
}
